use matrix_sdk::{
    config::SyncSettings,
    ruma::{
        api::client::{
            account::register::v3::Request as RegistrationRequest, error::ErrorKind,
            room::create_room::v3::Request as CreateRoomRequest,
        },
        events::room::message::SyncRoomMessageEvent,
        user_id,
    },
    Client,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let alice = user_id!("@alice:localhost:8000");
    let client = Client::builder()
        .insecure_server_name_no_tls(alice.server_name())
        .build()
        .await?;

    // First we need to log in.
    let mut request = RegistrationRequest::new();
    request.username = Some(alice.localpart().to_string());
    request.password = Some("password".to_string());

    let auth = client.matrix_auth();
    let register_res = auth.register(request).await;
    match register_res {
        Ok(r) => {
            println!("Registration successful: {:?}", r);
        }
        Err(e) => {
            if let Some(api_error) = e.client_api_error_kind() {
                match api_error {
                    ErrorKind::UserInUse => {
                        println!("User already exists, logging in instead");
                    }
                    _ => {
                        println!("Error registering: {:?}", e);
                        return Err(e.into());
                    }
                }
            }
        }
    }
    auth.login_username(alice, "password").send().await?;

    client.add_event_handler(|ev: SyncRoomMessageEvent| async move {
        println!("Received a message {:?}", ev);
    });

    // Syncing is important to synchronize the client state with the server.
    // This method will never return unless there is an error.
    let sync_client = client.clone();
    tokio::spawn(async move {
        let _ = sync_client.sync(SyncSettings::default()).await;
    });
    let mut request = CreateRoomRequest::new();
    request.name = Some("test_room".to_string());
    client.create_room(request).await?;
    // client.sync(SyncSettings::default()).await?;

    Ok(())
}
